/**
This is a derived version from DNDApplet - Modified to work with h3oUpload.

Modified by Thorsten Zoerner (me@thorsten-zoerner.com)

*/
/*******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

package dndapplet.applet;

import java.applet.*;

import javax.swing.*;
import javax.swing.border.*;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Container;
import java.awt.Color;
import java.awt.event.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.util.List;
import java.util.ArrayList;
import java.io.*;
import java.net.*;
import java.util.zip.*;

/**
 * This applet allows users to select files from their file system using drag 
 * and drop and upload them to a remote server.  All files will be zipped and 
 * sent to the server as a single file to improve upload performance.  This 
 * applet will use the HTTP protocol to communicate with the server.
 *
 */

class TruncOutput extends OutputStream {

	String url = null;
	HttpURLConnection conn = null;
	int trunc=0;
	int buf=0;
	OutputStream os = null;
	public TruncOutput(String url) {
		this.url=url;		
	}
	
	public void write(int b) throws IOException {
	if(this.conn==null) {
        conn = (HttpURLConnection) new URL(url+"&trunc="+trunc).openConnection();
        conn.setRequestMethod("PUT");
        conn.setFollowRedirects(false);
        conn.setRequestProperty("content-type", "application/zip");
        conn.setDoOutput(true);
        os = conn.getOutputStream();
        buf=0;
        
	}
	buf++;
	if(buf>1024*1024) {
		trunc++;
		buf=0;
		os.close();
		conn.connect();
		System.out.println("Transmitting Trunc "+trunc+":"+conn.getResponseCode());
		if(this.conn!=null) {
			this.conn.disconnect();
		}
		this.conn=null;
		this.write(b);
	} else os.write(b); 
	
	}
	
	public void close() throws IOException{
		super.close();
		os.close();
		conn.connect();
		System.out.println("Transmitting END "+trunc+":"+conn.getResponseCode());
		buf=0;		
	}
	
	public int getTrunc() {
		return this.trunc;
	}
	
}


public class DNDApplet extends Applet implements DropTargetListener, ActionListener
{
	JLabel title=null;
    /**
     * This label shows the user the files they have selected and their status.
     */
    private JLabel m_statusLabel;
    /**
     * This is the button which starts the upload process
     */
    private JButton m_updload;
    /**
     * This button is a link to the display images page
     */
    
    /**
     * This is the list of files which will be uploaded
     */
    private ArrayList m_fileList = new ArrayList();

    /**
     * The init method creates all of the UI controls and performs all of the 
     * layout of the UI.
     */
    public void init()
    {
        this.setLayout(new BorderLayout());        
        Container main = new Container();
        add(main,BorderLayout.CENTER);
        main.setLayout(new BorderLayout());
        //main.setLayout();

        
        /*
         * This label will also serve as our drop target so we want to
         * make sure it is big enough to be easy to drop files on to it.
         */
        String droptext="Drag and Drop your file here";
        int r=255;
        int g=255;
        int b=255;
        try {
        if(this.getParameter("r")!=null) r=Integer.parseInt(this.getParameter("r"));
        if(this.getParameter("g")!=null) r=Integer.parseInt(this.getParameter("g"));
        if(this.getParameter("b")!=null) r=Integer.parseInt(this.getParameter("b"));
        this.setBackground(new Color(r,g,b));
        } catch(Throwable t) {
        	System.out.println(t.getMessage());
        }
        if(this.getParameter("drop_text")!=null) {
        	droptext=this.getParameter("drop_text");        	
        }
        if(this.getParameter("drop_image")==null) {
            title = new JLabel(droptext);
        	title.setBackground(new Color(r,g,b));
        	title.setVerticalAlignment(SwingConstants.CENTER);
        	title.setHorizontalAlignment(SwingConstants.CENTER);
        } else {        	
        	try {
				title = new JLabel(new ImageIcon(new URL(this.getDocumentBase().toString()+this.getParameter("drop_image"))));
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				System.out.println("unable to load image"+e.getMessage());
				title = new JLabel(new ImageIcon(this.getParameter("drop_image")));
				title.setBackground(new Color(r,g,b));
			}        	
            title.setVerticalAlignment(SwingConstants.CENTER);
            title.setHorizontalAlignment(SwingConstants.CENTER);        	
        }
        
        DropTarget dt2 = new DropTarget(title, this);
        title.setBorder(new LineBorder(Color.black));
        title.setOpaque(true);
        main.add(title,BorderLayout.CENTER);
        

        /*
         * The files to upload label and list
         */
        JLabel files = new JLabel("Files to upload:");

        m_statusLabel = new JLabel();


        /*
         * The upload button
         */
        m_updload = new JButton("Upload");

   
    }

    /**
     * This method handles actually uploading the selected files to the server.
     */
    private void putData()
    {
        /*
         * This method needs to gather up each of the files the user has selected,
         * zip those files together, and send that zip file up to the server.
         */
        
        this.title.setText("please wait");
        try {
                        
            int j=0;                 
            StringBuffer info = new StringBuffer();
            for (int i = 0; i < m_fileList.size(); i++) {
                String url = getDocumentBase().toString();
                url = url + "index.php?checknum="+ this.getParameter("checknum");
                url = url + "&msg=javaUp";
                url = url + "&sid="+this.getParameter("sid");            
                int trunc=0;       
                
                /*
                 * For each file we will create a new entry in the ZIP archive and
                 * stream the file into that entry.
                 */
                File f = (File) m_fileList.get(i);
                String filename=f.getName();                
                filename=filename.replace(" ", "+");
                url = url + "&f="+filename;
                TruncOutput truncstream = new TruncOutput(url);
                info.append(f.getName());
                info.append("|");                                
                InputStream in = new FileInputStream(f);
                int read;
                byte[] buf = new byte[1024];
                while ((read = in.read(buf)) > 0) {
                	j++;
                	                	
                    truncstream.write(buf, 0, read);
                }
                this.title.setText("uploaded file "+(i+1));
                truncstream.close();
                in.close();
                trunc=truncstream.getTrunc();
                url = getDocumentBase().toString();
                url = url + "index.php?checknum="+ this.getParameter("checknum");
                url = url + "&msg=javaMerge";
                url = url + "&sid="+this.getParameter("sid"); 
                url = url + "&f="+filename;
                HttpURLConnection conn = (HttpURLConnection) new URL(url+"&trunc="+trunc).openConnection();
                conn.setRequestMethod("PUT");
                conn.setFollowRedirects(false);
                conn.setRequestProperty("content-type", "text/plain");
                conn.setDoOutput(true); 
                conn.connect();
                OutputStream outinfo = conn.getOutputStream();            
                                        
                outinfo.write(info.toString().getBytes(),0,0);            
                System.out.println(info.toString());
                outinfo.close();
                Thread.sleep(100);
                System.out.println("conn.getResponseCode(): " + conn.getResponseCode());
                conn.disconnect();
            }
                     
        
        this.m_fileList=new ArrayList();        
        } catch(Exception ex) {
        	this.title.setText(ex.getMessage());
        }
        try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        String droptext="Drag and Drop your file here";
        if(this.getParameter("drop_text")!=null) {
        	droptext=this.getParameter("drop_text");
        	this.title.setText(droptext);
        } else {
        	this.title.setText("");
        }
    }

    public void actionPerformed(ActionEvent e)
    {
        if (e.getSource() == m_updload) {
            putData();
        } 
    }

    public void dragExit(DropTargetEvent dte)
    {
        // System.out.println("dragExit(" + dte + ")");
    }

    public void dragEnter(DropTargetDragEvent dtde)
    {
        // System.out.println("dragenter(" + dtde + ")");
    }

    public void dragOver(DropTargetDragEvent dtde)
    {
        // System.out.println("dragOver(" + dtde + ")");
    }

    public void dropActionChanged(DropTargetDragEvent dtde)
    {
        // System.out.println("dropActionChanged(" + dtde + ")");
    }

    /**
     * This method will be called when the user drops a file on our target label.
     * 
     * @param dtde
     */
    public void drop(DropTargetDropEvent dtde)
    {
        int action = dtde.getDropAction();

        /*
         * We have to tell Java that we are going to accept this drop before
         * we try to access any of the data.
         */
        dtde.acceptDrop(action);

        fromTransferable(dtde.getTransferable());

        /*
         * Once the drop event is complete we need to notify Java again so it
         * can reset the cursor and finish showing the drop behavior.
         */
        dtde.dropComplete(true);
    }

    /**
     * This is a helper method to get the data from the drop event.
     * 
     * @param t
     */
    private void fromTransferable(Transferable t)
    {
        if (t == null)
            return;

        /*
         * The user may have dropped a file or anything else from any application
         * running on their computer.  This interaction is handled with data flavors.
         * For example, text copied from OpenOffice might have one flavor which 
         * contains the text with formatting information and another flavor which
         * contains the text without any of this information.  We need to look for
         * the data flavor we know how to support and read the list of files from it.
         */
        try {
            DataFlavor flavors[] = t.getTransferDataFlavors();
            if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                /*
                 * We are looking for the list of files data flavor.  This will be a
                 * list of the paths to the files the user dragged and dropped on to
                 * our application.
                 */
                List list = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
                m_fileList.addAll(list);

                /*
                 * We are going to take the path to each file and add it to the list
                 * so the user can see which files they have selected.
                 */
                StringBuffer sb = new StringBuffer();
                sb.append("<HTML><UL>");

                for (int i = 0; i < m_fileList.size(); i++) {
                    File f = (File) m_fileList.get(i);
                    sb.append("<LI>" + f + "</LI>\n");
                }

                sb.append("</UL></HTML>");

                m_statusLabel.setText(sb.toString());

                /*
                 * Now that we have at least one file to upload we can enable the 
                 * upload button.
                 */
                m_updload.setEnabled(true);
                this.putData();
            } else {
                /*
                 * There is a very large number of other data flavors the user can 
                 * drop onto our applet.  we will just show the information from 
                 * those types, but we can't get a list of files to upload from 
                 * them.
                 */
                DataFlavor df = DataFlavor.selectBestTextFlavor(flavors);

                JOptionPane.showMessageDialog(this, "df: " + df);

                JOptionPane.showMessageDialog(this, "t.getTransferData(df): " + t.getTransferData(df));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
